package models

import (
	"context"
	"errors"
	"github.com/golang-jwt/jwt/v4"
	"go-chain-api/global"
	"go-chain-api/tools"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"gorm.io/gorm"
	"log"
)

type User struct {
	Id               string `bson:"_id,omitempty" json:"id"`
	Username         string `bson:"username" json:"username"`
	Password         string `bson:"password" json:"password"`
	ApiKey           string `bson:"apiKey" json:"apiKey"`
	Status           int    `bson:"status" json:"status"`
	Email            string `bson:"email" json:"email"`
	MaturityTime     int64  `bson:"maturityTime" json:"maturityTime"`
	EmailCode        string `bson:"emailCode" json:"emailCode"`
	Role             string `bson:"role" json:"role"`
	DappMaturityTime int64  `bson:"dappMaturityTime" json:"dappMaturityTime"`
}

type UdunUser struct {
	gorm.Model
	Username           string `gorm:"unique"`
	Password           string
	CallBackUrl        string `json:"callBackUrl"`
	APIKey             string `json:"APIKey"`
	APISecret          string `json:"APISecret"`
	APIData            string `json:"APIData"` // 新增字段，用于存储生成签名所需的数据
	FeeAddress         string // 手续费地址（私钥）
	CollectAddress     string // 归集地址
	WithdrawAddress    string // 提币地址（私钥）
	FeeAddressTrx      string // 手续费地址（私钥）Trx
	CollectAddressTrx  string // 归集地址Trx
	WithdrawAddressTrx string // 提币地址（私钥）Trx
}

type Request struct {
	UserName  string `json:"user_name"`
	TokenName string `json:"token_name"`
	UserId    uint   `json:"user_id"`
	TokenId   uint   `json:"token_id"`
}

type Claims struct {
	Apikey string `json:"apikey"`
	jwt.StandardClaims
}

var JwtKey = []byte("my_secret_key")

// CheckUser 查询是否用户是否存在
func (u User) CheckUser(username string) (bool, error) {
	UserClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
	// 查找
	filter := bson.D{{"username", username}}
	documents, err := UserClient.CountDocuments(context.TODO(), filter)
	if err != nil {
		return false, err
	}

	if documents > 0 {
		return true, nil
	} else {
		return false, nil
	}
}

func (u User) CheckEmail(email string) (bool, error) {
	UserClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
	// 查找
	filter := bson.D{{"email", email}}
	documents, err := UserClient.CountDocuments(context.TODO(), filter)
	if err != nil {
		return false, err
	}

	if documents > 0 {
		return true, nil
	} else {
		return false, nil
	}
}

// GetUserByName 根据用户名获取用户
func (u User) GetUserByName(username string) (User, error) {
	UserClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
	// 查找
	filter := bson.D{{"username", username}, {"status", 1}}

	// 查找
	var user User
	err := UserClient.FindOne(context.TODO(), filter).Decode(user)
	if err != nil {
		return User{}, err
	}
	return user, nil
}

// GetUserByApiKey 根据ApiKey获取用户
func (u User) GetUserByApiKey(apiKey string) (User, error) {
	UserClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
	// 查找
	filter := bson.D{{"apiKey", apiKey}, {"status", 1}}

	// 查找
	var user User
	err := UserClient.FindOne(context.TODO(), filter).Decode(&user)
	if err != nil {
		return User{}, err
	}
	return user, nil
}

// GetUserByUsernameAndPassword 根据用户名和密码获取用户
func (u User) GetUserByUsernameAndPassword(username string, password string) (User, error) {
	UserClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
	// 查找
	filter := bson.D{{"username", username}, {"password", password}, {"status", 1}}
	var user User
	err := UserClient.FindOne(context.TODO(), filter).Decode(&user)
	if err != nil {
		return User{}, err
	}

	return user, nil
}

// CreateUser 创建用户
func (u User) CreateUser(user User) (string, error) {
	UserClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
	// 查找
	result, _ := u.CheckUser(user.Username)
	if result {
		return "", errors.New("username is exist")
	}

	emailRes, _ := u.CheckEmail(user.Email)
	if emailRes {
		return "", errors.New("email is exist")
	}

	// 创建用户
	data, err := UserClient.InsertOne(context.TODO(), user)
	if err != nil {
		return "", err
	}
	return data.InsertedID.(primitive.ObjectID).Hex(), nil
}

// CreateUdunUser 创建u盾用户
func (u User) CreateUdunUser(user User) error {
	var udunUser UdunUser
	udunUser.Username = user.Username
	udunUser.Password = user.Password
	//事务开启
	tx := global.MysqlDbEngine.Begin()
	err := tx.Table("tian_users").Create(&udunUser).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	//生成apikey
	udunUser.APIKey = user.ApiKey
	//生成APISecret
	udunUser.APISecret = tools.GenerateAPIKey(udunUser.Username, udunUser.CreatedAt)
	err = tx.Table("tian_users").Save(&udunUser).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

// UpdateUser 更新用户
func (u User) UpdateUser(user User) error {
	UserClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")

	// 查找
	result, _ := u.GetUserByName(user.Username)
	if result.Username != "" {
		return errors.New("用户名已存在")
	}

	// 更新(不可更新status和maturityTime)
	filter := bson.D{{"username", user.Username}}
	update := bson.D{{"$set", bson.D{{"password", user.Password}, {"email", user.Email}}}}

	_, err := UserClient.UpdateOne(context.TODO(), filter, update)
	if err != nil {
		return err
	}

	return nil
}

// UpdateMaturityTime 修改到期时间
func (u User) UpdateMaturityTime(user User) error {
	UserClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")

	// 查找
	result, _ := u.GetUserByName(user.Username)
	if result.Username == "" {
		return errors.New("用户不存在")
	}

	// 更新
	filter := bson.D{{"username", user.Username}}
	update := bson.D{{"$set", bson.D{{"maturityTime", user.MaturityTime}}}}

	_, err := UserClient.UpdateOne(context.TODO(), filter, update)
	if err != nil {
		return err
	}

	return nil
}

// UpdateUserStatus 修改用户状态
func (u User) UpdateUserStatus(user User) error {
	UserClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")

	// 查找
	result, _ := u.GetUserByName(user.Username)
	if result.Username == "" {
		return errors.New("用户不存在")
	}

	// 更新
	filter := bson.D{{"username", user.Username}}
	update := bson.D{{"$set", bson.D{{"status", user.Status}}}}

	_, err := UserClient.UpdateOne(context.TODO(), filter, update)
	if err != nil {
		return err
	}

	return nil
}

// CheckApiKey 判断apikey是否合法
func (u User) CheckApiKey(tokenString string) (error, User) {
	// 解析Token
	claims := &Claims{}
	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
		return JwtKey, nil
	})
	if err != nil || !token.Valid {
		return err, User{}
	}

	UserClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
	var user User
	// 查找
	filter := bson.D{{"apiKey", claims.Apikey}, {"status", 1}}
	//documents, err := UserClient.CountDocuments(context.TODO(), filter)
	err = UserClient.FindOne(context.TODO(), filter).Decode(&user)
	if err != nil {
		return err, User{}
	}
	return nil, user
}

// 删除用户
func (u User) DeleteById(id string) error {
	deleteResult, err := global.DBEngine.Database(global.DbConfig.DbName).Collection("user").DeleteOne(context.Background(), bson.M{
		"_id": id,
	})
	if err != nil {
		log.Fatalf("Failed to delete MongoDB document: %v", err)
		return err
	}
	if deleteResult.DeletedCount == 0 {
		log.Fatal("Failed to delete MongoDB document")
		return errors.New("Failed to delete MongoDB document")
	}
	return nil
}

func (u User) EditPassword() error {
	objId, _ := primitive.ObjectIDFromHex(u.Id)
	filter := bson.D{{"_id", objId}}
	update := bson.D{{"$set", bson.D{{"password", u.Password}}}}
	_, err := global.DBEngine.Database(global.DbConfig.DbName).Collection("user").UpdateOne(context.TODO(), filter, update)
	if err != nil {
		return err
	}
	return nil
}

func (u User) UpdateEmail(user User) error {
	UserClient := global.DBEngine.Database(global.DbConfig.DbName).Collection("user")
	// 查找
	//result, _ := u.CheckUserId(u.Id)
	//if result {
	//	return errors.New("username is exist")
	//}

	emailRes, err := u.CheckEmail(user.Email)
	if emailRes {
		return errors.New("email is exist")
	}
	//documents, err := UserClient.CountDocuments(context.TODO(), bson.D{{"email", user.Email}})
	if err != nil {
		return err
	}
	//if documents > 0 {
	//	return errors.New("email is exist")
	//}
	objId, _ := primitive.ObjectIDFromHex(u.Id)

	// 更新
	filter := bson.D{{"_id", objId}}
	update := bson.D{{"$set", bson.D{{"email", user.Email}}}}

	//data, err := UserClient.InsertOne(context.TODO(), user)
	_, err = UserClient.UpdateOne(context.TODO(), filter, update)
	if err != nil {
		return err
	}
	return err
}
